]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
St: avoid blocking IO to resolve relative urls
authorGiovanni Campagna <gcampagna@src.gnome.org>
Thu, 22 Nov 2012 00:13:59 +0000 (01:13 +0100)
committerGiovanni Campagna <gcampagna@src.gnome.org>
Sat, 15 Dec 2012 02:40:13 +0000 (03:40 +0100)
realpath() does a series of lstat() on each path component to resolve
symbolic links, but we just want to get an absolute path, and we don't
really care if it is physical or not. Going through a GFile does the
canonicalization we need, and is a lot faster.

https://bugzilla.gnome.org/show_bug.cgi?id=687881

src/st/st-theme-node.c
src/st/st-theme-private.h
src/st/st-theme.c

index 766e0733d07bf6f65a40a143e949916dbcf995e6..d049ca1538c188f23eaa391f5887fcbfe1b425fc 100644 (file)
@@ -1738,15 +1738,19 @@ _st_theme_node_ensure_background (StThemeNode *node)
               else if (term->type == TERM_URI)
                 {
                   CRStyleSheet *base_stylesheet;
+                  GFile *file;
 
                   if (decl->parent_statement != NULL)
                     base_stylesheet = decl->parent_statement->parent_sheet;
                   else
                     base_stylesheet = NULL;
 
-                  node->background_image = _st_theme_resolve_url (node->theme,
-                                                                  base_stylesheet,
-                                                                  term->content.str->stryng->str);
+                  file = _st_theme_resolve_url (node->theme,
+                                                base_stylesheet,
+                                                term->content.str->stryng->str);
+
+                  node->background_image = g_strdup (g_file_get_path (file));
+                  g_object_unref (file);
                 }
             }
         }
@@ -1843,6 +1847,7 @@ _st_theme_node_ensure_background (StThemeNode *node)
           if (decl->value->type == TERM_URI)
             {
               CRStyleSheet *base_stylesheet;
+              GFile *file;
 
               if (decl->parent_statement != NULL)
                 base_stylesheet = decl->parent_statement->parent_sheet;
@@ -1850,9 +1855,12 @@ _st_theme_node_ensure_background (StThemeNode *node)
                 base_stylesheet = NULL;
 
               g_free (node->background_image);
-              node->background_image = _st_theme_resolve_url (node->theme,
-                                                              base_stylesheet,
-                                                              decl->value->content.str->stryng->str);
+              file = _st_theme_resolve_url (node->theme,
+                                            base_stylesheet,
+                                            decl->value->content.str->stryng->str);
+
+              node->background_image = g_strdup (g_file_get_path (file));
+              g_object_unref (file);
             }
           else if (term_is_inherit (decl->value))
             {
@@ -2668,6 +2676,7 @@ st_theme_node_get_border_image (StThemeNode *node)
           int border_bottom;
           int border_left;
 
+          GFile *file;
           char *filename;
 
           /* Support border-image: none; to suppress a previously specified border image */
@@ -2746,7 +2755,10 @@ st_theme_node_get_border_image (StThemeNode *node)
           else
             base_stylesheet = NULL;
 
-          filename = _st_theme_resolve_url (node->theme, base_stylesheet, url);
+          file = _st_theme_resolve_url (node->theme, base_stylesheet, url);
+          filename = g_strdup (g_file_get_path (file));
+          g_object_unref (file);
+
           if (filename == NULL)
             goto next_property;
 
index ecd2639bec210f945feb065121101d5f9df99ba2..08f3a18643f93ca89b5cc1a917deaf85958de447 100644 (file)
@@ -29,10 +29,10 @@ G_BEGIN_DECLS
 GPtrArray *_st_theme_get_matched_properties (StTheme       *theme,
                                              StThemeNode   *node);
 
-/* Resolve an URL from the stylesheet to a filename */
-char *_st_theme_resolve_url (StTheme      *theme,
-                             CRStyleSheet *base_stylesheet,
-                             const char   *url);
+/* Resolve an URL from the stylesheet to a file */
+GFile *_st_theme_resolve_url (StTheme      *theme,
+                              CRStyleSheet *base_stylesheet,
+                              const char   *url);
 
 CRDeclaration *_st_theme_parse_declaration_list (const char *str);
 
index 4012ab9a4bb38967debed4b35c68a66859815d93..601f31eebaa5dd669d86b20ed581abd59c166216 100644 (file)
@@ -849,9 +849,16 @@ add_matched_properties (StTheme      *a_this,
                 char *filename = NULL;
 
                 if (import_rule->url->stryng && import_rule->url->stryng->str)
-                  filename = _st_theme_resolve_url (a_this,
-                                                    a_nodesheet,
-                                                    import_rule->url->stryng->str);
+                  {
+                    GFile *file;
+
+                    file = _st_theme_resolve_url (a_this,
+                                                  a_nodesheet,
+                                                  import_rule->url->stryng->str);
+                    filename = g_strdup (g_file_get_path (file));
+
+                    g_object_unref (file);
+                  }
 
                 if (filename)
                   import_rule->sheet = parse_stylesheet (filename, NULL);
@@ -999,84 +1006,41 @@ _st_theme_get_matched_properties (StTheme        *theme,
  * local filename, if possible. The resolution here is distinctly lame and
  * will fail on many examples.
  */
-char *
+GFile *
 _st_theme_resolve_url (StTheme      *theme,
                        CRStyleSheet *base_stylesheet,
                        const char   *url)
 {
-  const char *base_filename = NULL;
-  char *dirname;
-  char *filename;
-  char *canonicalized_path;
-
-  /* Handle absolute file:/ URLs */
-  if (g_str_has_prefix (url, "file:") ||
-      g_str_has_prefix (url, "File:") ||
-      g_str_has_prefix (url, "FILE:"))
-    {
-      GError *error = NULL;
-      char *filename;
-
-      filename = g_filename_from_uri (url, NULL, &error);
-      if (filename == NULL)
-        {
-          g_warning ("%s", error->message);
-          g_error_free (error);
-        }
-
-      return filename;
-    }
-
-  /* Guard against http:/ URLs */
+  char *scheme;
+  GFile *stylesheet, *resource;
 
-  if (g_str_has_prefix (url, "http:") ||
-      g_str_has_prefix (url, "Http:") ||
-      g_str_has_prefix (url, "HTTP:"))
+  if ((scheme = g_uri_parse_scheme (url)))
     {
-      g_warning ("Http URL '%s' in theme stylesheet is not supported", url);
-      return NULL;
+      g_free (scheme);
+      resource = g_file_new_for_uri (url);
     }
-
-  /* Assume anything else is a relative URL, and "resolve" it
-   */
-  if (url[0] == '/')
+  else if (base_stylesheet != NULL)
     {
-      canonicalized_path = realpath (url, NULL);
-      if (g_mem_is_system_malloc ())
-        {
-          filename = canonicalized_path;
-        }
-      else
-        {
-          filename = g_strdup (canonicalized_path);
-          free (canonicalized_path);
-        }
-      return filename;
-    }
+      const char *base_filename = NULL;
+      char *dirname;
 
-  base_filename = g_hash_table_lookup (theme->filenames_by_stylesheet, base_stylesheet);
+      base_filename = g_hash_table_lookup (theme->filenames_by_stylesheet, base_stylesheet);
 
-  if (base_filename == NULL)
-    {
-      g_warning ("Can't get base to resolve url '%s'", url);
-      return NULL;
-    }
+      /* This is an internal function, if we get here with
+         a bad @base_stylesheet we have a problem. */
+      g_assert (base_filename);
 
-  dirname = g_path_get_dirname (base_filename);
-  filename = g_build_filename (dirname, url, NULL);
-  canonicalized_path = realpath (filename, NULL);
-  g_free (dirname);
-  g_free (filename);
+      dirname = g_path_get_dirname (base_filename);
+      stylesheet = g_file_new_for_path (dirname);
+      resource = g_file_resolve_relative_path (stylesheet, url);
 
-  if (g_mem_is_system_malloc ())
-    {
-      filename = canonicalized_path;
+      g_object_unref (stylesheet);
+      g_free (dirname);
     }
   else
     {
-      filename = g_strdup (canonicalized_path);
-      free (canonicalized_path);
+      resource = g_file_new_for_path (url);
     }
 
-  return filename;
+  return resource;
 }